package org.beetl.json.node;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import org.beetl.json.ActionComparator;
import org.beetl.json.ActionReturn;
import org.beetl.json.JsonTool;
import org.beetl.json.JsonWriter;
import org.beetl.json.Location;
import org.beetl.json.LocationAction;
import org.beetl.json.OutputNode;
import org.beetl.json.action.IKeyAction;
import org.beetl.json.action.IValueAction;
import org.beetl.json.util.JsonUtil;
import org.beetl.json.util.MethodInvoker;
import org.beetl.json.util.Type;

public class PojoAttributeNode implements OutputNode {

	protected Class parent;
	protected String attrName;
	protected char[] atrrNameChars = null;
	protected Class attrType;
	protected MethodInvoker methodProxy = null;
	protected  TreeSet<IKeyAction>  keyActions =  new TreeSet(new ActionComparator<IKeyAction>());
	protected  TreeSet<IValueAction>  valueActions =  new TreeSet(new ActionComparator<IValueAction>());

	public PojoAttributeNode(Class parent,Method m){
		this.parent = parent ;
		this.attrType = m.getReturnType();
		this.attrName = JsonUtil.getAttribute(m);
		methodProxy = new MethodInvoker(parent,m,attrName);
		if(valueActions.size()==0){
			methodProxy.returnType = Type.getType(m.getReturnType());
		}
		if(keyActions.size()==0){
			char c = JsonTool.UseSingleQuotes?'\'':'\"';
			StringBuilder sb = new StringBuilder(attrName.length()+2).append(c).append(attrName).append(c).append(":");
			atrrNameChars = sb.toString().toCharArray();
		}
		
	
	}
	@Override
	public  void render(Object obj,JsonWriter w) throws IOException{		
		
		if(this.writeKey( w)){
		
			this.writeValue(obj, w);			
		}
	
	}
	
	
	
	@Override
	public void setActionByLocation(List<Location> list) {
		for(Location l:list){
			if(isMatch(l)){
				LocationAction action = l.getAction();
				if(action instanceof IKeyAction){
					this.keyActions.add((IKeyAction)action);
				}else if(action instanceof IValueAction){
					this.valueActions.add( (IValueAction)action);
				}
			}
		}
		
	}
	
	
	protected boolean writeKey(JsonWriter w) throws IOException{
		String key = attrName;			
		if(this.keyActions.size()!=0){
			ActionReturn ar = null;
			for(IKeyAction keyAction:keyActions){
				ar = (ActionReturn)keyAction.doit(key, this);
				if(ar.process){
					key = (String)ar.value;
				}else{
					key = (String)ar.value;
					if(key==null) return  false;
				}
				
			}
			w.writeKey(key);		
			w.write(':');
			return true;
				
		}else{
			w.writeChars(atrrNameChars);
			return true ;
		}
	
		
	}
	
	protected void writeValue(Object owener,JsonWriter w) throws IOException{
		Object attrValue = methodProxy.invoke(owener);
		if(valueActions.size()==0){
			switch(methodProxy.returnType){
			case Type.JAVA_TYPE:w.write(attrValue);return;
			case Type.Collection_TYPE:NodeUtil.writeIterator(this, ((Iterable)attrValue).iterator(), w);return ;
			case Type.MAP_TYPE:NodeUtil.writeMap(this, (Map)attrValue, w);return ;
			case Type.POJO_TYPE:{
				JsonTool.serializeJW(w,attrValue);
			}
			default:{
				NodeUtil.writeUnkonw(this, attrValue, w, valueActions);
			}
			}
			
			
		}else{
			NodeUtil.writeUnkonw(this, attrValue, w, valueActions);
		}
		 
		
		
		
	}

	
	
	protected boolean isMatch(Location location) {
		return location.match(this.attrType, this.attrName);
	}

	public String getAttrName() {
		return attrName;
	}
	public void setAttrName(String attrName) {
		this.attrName = attrName;
	}
	public Class getAttrType() {
		return attrType;
	}
	public void setAttrType(Class attrType) {
		this.attrType = attrType;
	}
	

}
